home *** CD-ROM | disk | FTP | other *** search
/ The Complete Utilities To…ka 501 Killer Utilities! / 501 Killer Utilities! (Macworld July 1995).cdr / Programming / OutOfPhase1.1 Source / OutOfPhase Folder / Level 1 Extensions 04Jan95 / Alert.c next >
Encoding:
C/C++ Source or Header  |  1995-01-01  |  14.9 KB  |  517 lines  |  [TEXT/KAHL]

  1. /* Alert.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Debug.h"
  21. #include "Audit.h"
  22. #include "Definitions.h"
  23.  
  24. #include "Alert.h"
  25. #include "Screen.h"
  26. #include "DataMunging.h"
  27. #include "Memory.h"
  28. #include "EventLoop.h"
  29. #include "SimpleButton.h"
  30. #include "WrapTextBox.h"
  31. #include "Menus.h"
  32.  
  33.  
  34. #define ALERTEMERGENCY (20480)
  35.  
  36. #define ALERTWIDTH (400)
  37. #define ALERTHEIGHT (160)
  38.  
  39. #define DLOGWIDTH (400)
  40. #define DLOGHEIGHT (180)
  41.  
  42. #define BUTTONWIDTH (93)
  43.  
  44. static unsigned char                RawStopIcon[] =
  45.     {
  46.         0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0x80,0x01,0xC0,0x07,0x7F,0xFE,0xE0,
  47.         0x0E,0xFF,0xFF,0x70,0x1D,0xFF,0xFF,0xB8,0x3B,0xFF,0xFF,0xDC,0x77,0xFF,0xFF,0xEE,
  48.         0xEF,0xFF,0xFF,0xF7,0xDF,0xFD,0x3F,0xFB,0xDF,0xF9,0x2F,0xFB,0xDF,0xE9,0x27,0xFB,
  49.         0xDF,0xC9,0x27,0xFB,0xDF,0xC9,0x27,0xFB,0xDF,0xC8,0x24,0xFB,0xDF,0xC0,0x04,0xFB,
  50.         0xDF,0xC0,0x00,0xFB,0xDF,0xC0,0x01,0xFB,0xDF,0xC0,0x01,0xFB,0xDF,0xC0,0x01,0xFB,
  51.         0xDF,0xE0,0x03,0xFB,0xDF,0xE0,0x03,0xFB,0xDF,0xF0,0x07,0xFB,0xDF,0xF8,0x0F,0xFB,
  52.         0xEF,0xFF,0xFF,0xF7,0x77,0xFF,0xFF,0xEE,0x3B,0xFF,0xFF,0xDC,0x1D,0xFF,0xFF,0xB8,
  53.         0x0E,0xFF,0xFF,0x70,0x07,0x00,0x00,0xE0,0x03,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x80
  54.     };
  55.  
  56. static unsigned char                RawExclamationIcon[] =
  57.     {
  58.         0x00,0x01,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x02,0x80,0x00,0x00,0x06,0xC0,0x00,
  59.         0x00,0x04,0x40,0x00,0x00,0x0C,0x60,0x00,0x00,0x08,0x20,0x00,0x00,0x1B,0xB0,0x00,
  60.         0x00,0x13,0x90,0x00,0x00,0x37,0xD8,0x00,0x00,0x27,0xC8,0x00,0x00,0x67,0xCC,0x00,
  61.         0x00,0x47,0xC4,0x00,0x00,0xC7,0xC6,0x00,0x00,0x87,0xC2,0x00,0x01,0x83,0x83,0x00,
  62.         0x01,0x03,0x81,0x00,0x03,0x03,0x81,0x80,0x02,0x03,0x80,0x80,0x06,0x03,0x80,0xC0,
  63.         0x04,0x01,0x00,0x40,0x0C,0x01,0x00,0x60,0x08,0x01,0x00,0x20,0x18,0x01,0x00,0x30,
  64.         0x10,0x00,0x00,0x10,0x30,0x01,0x80,0x18,0x20,0x03,0xC0,0x08,0x60,0x03,0xC0,0x0C,
  65.         0x40,0x01,0x80,0x04,0xC0,0x00,0x00,0x06,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFC
  66.     };
  67.  
  68. static unsigned char                RawSpeechIcon[] =
  69.     {
  70.         0x00,0x00,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x08,0x00,0x06,0x00,0x08,0x00,0x05,0x00,
  71.         0x08,0x00,0x04,0x80,0x08,0x00,0x04,0x40,0x08,0x00,0x04,0x20,0x08,0x00,0x07,0xF0,
  72.         0x0B,0xE0,0x00,0x10,0x08,0x84,0xF2,0x58,0x08,0x80,0x00,0x18,0x08,0x80,0x00,0x18,
  73.         0x08,0x86,0x79,0x98,0x08,0x80,0x00,0x18,0x0B,0xE0,0x00,0x18,0x08,0x07,0x79,0x98,
  74.         0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,0x0A,0xF2,0xE3,0x98,0x08,0x00,0x00,0x18,
  75.         0x08,0x00,0x00,0x18,0x0B,0xBB,0xB2,0x58,0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,
  76.         0x0A,0xFD,0x79,0x98,0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,0x0B,0x5B,0x90,0x18,
  77.         0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,0x0F,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xF8
  78.     };
  79.  
  80.  
  81. static Bitmap*                SpeechIcon;
  82. static Bitmap*                ExclamationIcon;
  83. static Bitmap*                StopIcon;
  84.  
  85. EXECUTE(static MyBoolean Initialized = False;)
  86.  
  87. static char*                    EmergencyMemory;
  88.  
  89.  
  90. /* initialize the alert system, allocate the bitmaps and temporary memory stash */
  91. MyBoolean                    InitializeAlertSubsystem(void)
  92.     {
  93.         ERROR(Initialized,PRERR(ForceAbort,
  94.             "InitializeAlertSubsystem called more than once"));
  95.         EXECUTE(Initialized = True);
  96.         SpeechIcon = MakeBitmap(RawSpeechIcon,32,32,4);
  97.         if (SpeechIcon == NIL)
  98.             {
  99.              FailurePoint1:
  100.                 return False;
  101.             }
  102.         ExclamationIcon = MakeBitmap(RawExclamationIcon,32,32,4);
  103.         if (ExclamationIcon == NIL)
  104.             {
  105.              FailurePoint2:
  106.                 DisposeBitmap(SpeechIcon);
  107.                 goto FailurePoint1;
  108.             }
  109.         StopIcon = MakeBitmap(RawStopIcon,32,32,4);
  110.         if (StopIcon == NIL)
  111.             {
  112.              FailurePoint3:
  113.                 DisposeBitmap(ExclamationIcon);
  114.                 goto FailurePoint2;
  115.             }
  116.         EmergencyMemory = AllocPtrCanFail(ALERTEMERGENCY,"AlertEmergencyPtr");
  117.         if (EmergencyMemory == NIL)
  118.             {
  119.              FailurePoint4:
  120.                 DisposeBitmap(StopIcon);
  121.                 goto FailurePoint3;
  122.             }
  123.         return True;
  124.     }
  125.  
  126.  
  127. /* clean up internal data structures */
  128. void                            ShutdownAlertSubsystem(void)
  129.     {
  130.         ERROR(!Initialized,PRERR(ForceAbort,"Alert subsystem not initialized"));
  131.         DisposeBitmap(SpeechIcon);
  132.         DisposeBitmap(ExclamationIcon);
  133.         DisposeBitmap(StopIcon);
  134.         if (EmergencyMemory != NIL)
  135.             {
  136.                 ReleasePtr(EmergencyMemory);
  137.             }
  138.     }
  139.  
  140.  
  141. typedef struct
  142.     {
  143.         WinType*                        ScreenID;
  144.         char*                                TotalMessage;
  145.         SimpleButtonRec*        OKButton;
  146.         Bitmap*                            IconThing;
  147.     } AlertRec;
  148.  
  149.  
  150. static void                AlertUpdater(AlertRec* Window)
  151.     {
  152.         /* DON'T call CheckPtrExistence since Window is allocated on the stack */
  153.         SetClipRect(Window->ScreenID,0,0,ALERTWIDTH,ALERTHEIGHT);
  154.         DrawBitmap(Window->ScreenID,23,13,Window->IconThing);
  155.         DrawWrappedTextBox(Window->ScreenID,Window->TotalMessage,GetUglyFont(),12,
  156.             23 + 32 + 23,13,ALERTWIDTH - (23 + 32 + 23 + 13) - 10,
  157.             ALERTHEIGHT - (13 + 13 + 21 + 6));
  158.         RedrawSimpleButton(Window->OKButton);
  159.     }
  160.  
  161.  
  162. static void                LocalAlert(Bitmap* TheIcon, char* Message, char* ExtraInfo)
  163.     {
  164.         AlertRec                Window;
  165.         EXECUTE(static MyBoolean    Alerting = False;)
  166.  
  167.         APRINT(("+LocalAlert: '%t' '%t'",Message,ExtraInfo));
  168.         ERROR(!Initialized,PRERR(ForceAbort,"Alert subsystem not initialized"));
  169.         ERROR(Message == NIL,PRERR(ForceAbort,"LocalAlert:  Message is NIL"));
  170.         ERROR(Alerting,PRERR(ForceAbort,"LocalAlert called recursively"));
  171.         EXECUTE(Alerting = True;)
  172.         if (EmergencyMemory != NIL)
  173.             {
  174.                 ReleasePtr(EmergencyMemory);
  175.                 EmergencyMemory = NIL;
  176.             }
  177.         ErrorBeep();
  178.         SetArrowCursor();
  179.         if (ExtraInfo != NIL)
  180.             {
  181.                 char*                    Key;
  182.                 char*                    Replacement;
  183.                 char*                    Original;
  184.                 char*                    Temp;
  185.  
  186.                 Key = BlockFromRaw("_",1);
  187.                 Replacement = BlockFromRaw(ExtraInfo,StrLen(ExtraInfo));
  188.                 Original = BlockFromRaw(Message,StrLen(Message));
  189.                 if ((Key == NIL) || (Replacement == NIL) || (Original == NIL))
  190.                     {
  191.                         /* we don't care about releasing the memory since this is a fatal */
  192.                         /* error anyway. */
  193.                      Fault:
  194.                         PRERR(ForceAbort,"Out of memory in alert handler -- can't continue");
  195.                     }
  196.                 Temp = ReplaceBlockCopy(Original,Key,Replacement);
  197.                 if (Temp == NIL)
  198.                     {
  199.                         goto Fault;
  200.                     }
  201.                 ReleasePtr(Key);
  202.                 ReleasePtr(Replacement);
  203.                 ReleasePtr(Original);
  204.                 Window.TotalMessage = BlockToStringCopy(Temp);
  205.                 ReleasePtr(Temp);
  206.                 if (Window.TotalMessage == NIL)
  207.                     {
  208.                         goto Fault;
  209.                     }
  210.             }
  211.          else
  212.             {
  213.                 Window.TotalMessage = StringFromRaw(Message);
  214.             }
  215.         Window.IconThing = TheIcon;
  216.         Window.ScreenID = MakeNewWindow(eModelessDialogWindow,eWindowNotClosable,
  217.             eWindowNotZoomable,eWindowNotResizable,AlertLeftEdge(ALERTWIDTH),
  218.             AlertTopEdge(ALERTHEIGHT),ALERTWIDTH,ALERTHEIGHT,
  219.             (void (*)(void*))&AlertUpdater,&Window);
  220.         if (Window.ScreenID == NIL)
  221.             {
  222.                 goto Fault;
  223.             }
  224.         Window.OKButton = NewSimpleButton(Window.ScreenID,"OK",ALERTWIDTH
  225.             - (13 + BUTTONWIDTH),ALERTHEIGHT - (13 + 21 + 3),BUTTONWIDTH,21);
  226.         if (Window.OKButton == NIL)
  227.             {
  228.                 goto Fault;
  229.             }
  230.         SetDefaultButtonState(Window.OKButton,True);
  231.         while (True)
  232.             {
  233.                 OrdType                            X,Y;
  234.                 ModifierFlags                Modifiers;
  235.                 WinType*                        TheWindow;
  236.                 MenuItemType*                MenuItem;
  237.                 char                                KeyPressed;
  238.  
  239.                 switch (GetAnEvent(&X,&Y,&Modifiers,&TheWindow,&MenuItem,&KeyPressed))
  240.                     {
  241.                         default:
  242.                             break;
  243.                         case eCheckCursor:
  244.                             SetArrowCursor();
  245.                             break;
  246.                         case eNoEvent:
  247.                             break;
  248.                         case eMouseDown:
  249.                             if (SimpleButtonHitTest(Window.OKButton,X,Y))
  250.                                 {
  251.                                     if (SimpleButtonMouseDown(Window.OKButton,X,Y,NIL,NIL))
  252.                                         {
  253.                                          ExitPoint:
  254.                                             DisposeSimpleButton(Window.OKButton);
  255.                                             ReleasePtr(Window.TotalMessage);
  256.                                             KillWindow(Window.ScreenID);
  257.                                             EXECUTE(Alerting = False;)
  258.                                             EmergencyMemory = AllocPtrCanFail(ALERTEMERGENCY,
  259.                                                 "AlertEmergencyPtr");
  260.                                             APRINT(("-LocalAlert"));
  261.                                             return;
  262.                                         }
  263.                                 }
  264.                             break;
  265.                         case eKeyPressed:
  266.                             if (KeyPressed == 13)
  267.                                 {
  268.                                     FlashButton(Window.OKButton);
  269.                                     goto ExitPoint;
  270.                                 }
  271.                             break;
  272.                     }
  273.             }
  274.         APRINT(("-LocalAlert"));
  275.     }
  276.  
  277.  
  278. /* display a halt (Stopsign) alert.  ExtraInfo is inserted into Message where */
  279. /* the _ character is */
  280. void                            AlertHalt(char* Message, char* ExtraInfo)
  281.     {
  282.         LocalAlert(StopIcon,Message,ExtraInfo);
  283.     }
  284.  
  285.  
  286. /* display a warning (!) alert. ExtraInfo is inserted into Message where */
  287. /* the _ character is */
  288. void                            AlertWarning(char* Message, char* ExtraInfo)
  289.     {
  290.         LocalAlert(ExclamationIcon,Message,ExtraInfo);
  291.     }
  292.  
  293.  
  294. /* display an informational (I) alert. ExtraInfo is inserted into Message where */
  295. /* the _ character is */
  296. void                            AlertInfo(char* Message, char* ExtraInfo)
  297.     {
  298.         LocalAlert(SpeechIcon,Message,ExtraInfo);
  299.     }
  300.  
  301.  
  302. typedef struct
  303.     {
  304.         WinType*                        ScreenID;
  305.         char*                                TotalMessage;
  306.         SimpleButtonRec*        YesButton;
  307.         SimpleButtonRec*        NoButton;
  308.         SimpleButtonRec*        CancelButton;
  309.     } YesNoCancelRec;
  310.  
  311.  
  312. static void                YesNoCancelUpdater(YesNoCancelRec* Window)
  313.     {
  314.         /* do NOT call CheckPtrExistence since Window is allocated on the stack */
  315.         SetClipRect(Window->ScreenID,0,0,DLOGWIDTH,DLOGHEIGHT);
  316.         DrawBitmap(Window->ScreenID,23,13,ExclamationIcon);
  317.         DrawWrappedTextBox(Window->ScreenID,Window->TotalMessage,GetUglyFont(),12,
  318.             23 + 32 + 23,13,DLOGWIDTH - (23 + 32 + 23 + 13) - 16,
  319.             DLOGHEIGHT - (13 + 13 + 21 + 6));
  320.         RedrawSimpleButton(Window->YesButton);
  321.         RedrawSimpleButton(Window->NoButton);
  322.         if (Window->CancelButton != NIL)
  323.             {
  324.                 RedrawSimpleButton(Window->CancelButton);
  325.             }
  326.     }
  327.  
  328.  
  329. /* present a dialog with 3 buttons (yes, no, and cancel).  if Cancel is NIL, */
  330. /* then there will only be 2 buttons.  ExtraInfo is inserted into Message where */
  331. /* the _ character is */
  332. YesNoCancelType        AskYesNoCancel(char* Message, char* ExtraInfo,
  333.                                         char* Yes, char* No, char* Cancel)
  334.     {
  335.         YesNoCancelRec            Window;
  336.         YesNoCancelType            ReturnValue;
  337.  
  338.         ERROR(!Initialized,PRERR(ForceAbort,"Alert subsystem not initialized"));
  339.         if (ExtraInfo != NIL)
  340.             {
  341.                 MyBoolean            Error;
  342.                 char*                    Key;
  343.                 char*                    Replacement;
  344.                 char*                    Original;
  345.                 char*                    Temp;
  346.  
  347.                 Error = False;
  348.                 Key = BlockFromRaw("_",1);
  349.                 if (Key != NIL)
  350.                     {
  351.                         Replacement = BlockFromRaw(ExtraInfo,StrLen(ExtraInfo));
  352.                         if (Replacement != NIL)
  353.                             {
  354.                                 Original = BlockFromRaw(Message,StrLen(Message));
  355.                                 if (Original != NIL)
  356.                                     {
  357.                                         Temp = ReplaceBlockCopy(Original,Key,Replacement);
  358.                                         if (Temp != NIL)
  359.                                             {
  360.                                                 Window.TotalMessage = BlockToStringCopy(Temp);
  361.                                                 ReleasePtr(Temp);
  362.                                                 if (Window.TotalMessage == NIL)
  363.                                                     {
  364.                                                         Error = True;
  365.                                                     }
  366.                                             }
  367.                                          else
  368.                                             {
  369.                                                 Error = True;
  370.                                             }
  371.                                         ReleasePtr(Original);
  372.                                     }
  373.                                  else
  374.                                     {
  375.                                         Error = True;
  376.                                     }
  377.                                 ReleasePtr(Replacement);
  378.                             }
  379.                          else
  380.                             {
  381.                                 Error = True;
  382.                             }
  383.                         ReleasePtr(Key);
  384.                     }
  385.                  else
  386.                     {
  387.                         Error = True;
  388.                     }
  389.                 if (Error)
  390.                     {
  391.                         return eCancel;
  392.                     }
  393.             }
  394.          else
  395.             {
  396.                 Window.TotalMessage = StringFromRaw(Message);
  397.                 if (Window.TotalMessage == NIL)
  398.                     {
  399.                         return eCancel;
  400.                     }
  401.             }
  402.         SetArrowCursor();
  403.         Window.ScreenID = MakeNewWindow(eModelessDialogWindow,eWindowNotClosable,
  404.             eWindowNotZoomable,eWindowNotResizable,DialogLeftEdge(DLOGWIDTH),
  405.             DialogTopEdge(DLOGHEIGHT),DLOGWIDTH,DLOGHEIGHT,
  406.             (void (*)(void*))&YesNoCancelUpdater,&Window);
  407.         if (Window.ScreenID == 0)
  408.             {
  409.              MemOut1:
  410.                 ReleasePtr(Window.TotalMessage);
  411.                 return eCancel;
  412.             }
  413.         Window.YesButton = NewSimpleButton(Window.ScreenID,Yes,DLOGWIDTH
  414.             - (13 + BUTTONWIDTH),DLOGHEIGHT - (13 + 21 + 3),BUTTONWIDTH,21);
  415.         if (Window.YesButton == NIL)
  416.             {
  417.              MemOut2:
  418.                 KillWindow(Window.ScreenID);
  419.                 goto MemOut1;
  420.             }
  421.         SetDefaultButtonState(Window.YesButton,True);
  422.         Window.NoButton = NewSimpleButton(Window.ScreenID,No,13,
  423.             DLOGHEIGHT - (13 + 21 + 3),BUTTONWIDTH,21);
  424.         if (Window.NoButton == NIL)
  425.             {
  426.              MemOut3:
  427.                 DisposeSimpleButton(Window.YesButton);
  428.                 goto MemOut2;
  429.             }
  430.         if (Cancel != NIL)
  431.             {
  432.                 Window.CancelButton = NewSimpleButton(Window.ScreenID,Cancel,DLOGWIDTH
  433.                     - (13 + BUTTONWIDTH),DLOGHEIGHT - (13 + 21 + 3 + 21 + 10),BUTTONWIDTH,21);
  434.                 if (Window.CancelButton == NIL)
  435.                     {
  436.                      MemOut4:
  437.                         DisposeSimpleButton(Window.NoButton);
  438.                         goto MemOut3;
  439.                     }
  440.             }
  441.          else
  442.             {
  443.                 Window.CancelButton = NIL;
  444.             }
  445.         while (True)
  446.             {
  447.                 OrdType                            X,Y;
  448.                 ModifierFlags                Modifiers;
  449.                 WinType*                        TheWindow;
  450.                 MenuItemType*                MenuItem;
  451.                 char                                Key;
  452.  
  453.                 switch (GetAnEvent(&X,&Y,&Modifiers,&TheWindow,&MenuItem,&Key))
  454.                     {
  455.                         default:
  456.                             break;
  457.                         case eCheckCursor:
  458.                             SetArrowCursor();
  459.                             break;
  460.                         case eNoEvent:
  461.                             break;
  462.                         case eMouseDown:
  463.                             if (SimpleButtonHitTest(Window.YesButton,X,Y))
  464.                                 {
  465.                                     if (SimpleButtonMouseDown(Window.YesButton,X,Y,NIL,NIL))
  466.                                         {
  467.                                             ReturnValue = eYes;
  468.                                             goto ExitPoint;
  469.                                         }
  470.                                 }
  471.                             else if (SimpleButtonHitTest(Window.NoButton,X,Y))
  472.                                 {
  473.                                     if (SimpleButtonMouseDown(Window.NoButton,X,Y,NIL,NIL))
  474.                                         {
  475.                                             ReturnValue = eNo;
  476.                                             goto ExitPoint;
  477.                                         }
  478.                                 }
  479.                             else if ((Window.CancelButton != NIL)
  480.                                 && SimpleButtonHitTest(Window.CancelButton,X,Y))
  481.                                 {
  482.                                     if (SimpleButtonMouseDown(Window.CancelButton,X,Y,NIL,NIL))
  483.                                         {
  484.                                             ReturnValue = eCancel;
  485.                                             goto ExitPoint;
  486.                                         }
  487.                                 }
  488.                             break;
  489.                         case eKeyPressed:
  490.                             if (Key == 13)
  491.                                 {
  492.                                     FlashButton(Window.YesButton);
  493.                                     ReturnValue = eYes;
  494.                                     goto ExitPoint;
  495.                                 }
  496.                             else if ((Key == eCancelKey) && (Window.CancelButton != NIL))
  497.                                 {
  498.                                     FlashButton(Window.CancelButton);
  499.                                     ReturnValue = eCancel;
  500.                                     goto ExitPoint;
  501.                                 }
  502.                             break;
  503.                     }
  504.             }
  505.  
  506.      ExitPoint:
  507.         DisposeSimpleButton(Window.YesButton);
  508.         DisposeSimpleButton(Window.NoButton);
  509.         if (Window.CancelButton != NIL)
  510.             {
  511.                 DisposeSimpleButton(Window.CancelButton);
  512.             }
  513.         ReleasePtr(Window.TotalMessage);
  514.         KillWindow(Window.ScreenID);
  515.         return ReturnValue;
  516.     }
  517.